package com.psct.music;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.provider.MediaStore;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;

import com.psct.Constant;
import com.psct.PSCTUtil;
import com.psct.R;
import com.psct.ThreadPool;
import com.psct.bean.Mp3Data;
import com.psct.bean.Mp3Res;
import com.psct.web.HttpUtil;

//播放音乐服务
public class MusicService extends Service {
	public static Context context;
	private static final int INTIAL_KB_BUFFER = 80;
	// private ImageView playButton;
	private int totalKbRead = 0;
	private int readHistory = 0;
	private final Handler handler = new Handler();
	/**
	 * 下载的音频文件
	 */
	private File downloadingMediaFile;
	private boolean isInterrupted;
	private int count = 0;
	private Runnable r;
	private Thread playerThread;
	private LocalBinder localBinder = new LocalBinder();
	private MediaPlayer player;
	private boolean isPause = true;
	private boolean destroyed = false;
	private InputStream stream;
	private boolean completed = false;
	/**
	 * 网络模式下mp3列表
	 */
	private List<Mp3Data> mp3List;
	/**
	 * 网络模式下当前播放的mp3文件；
	 */
	private Mp3Data mp3;

	@Override
	public void onCreate() {
		super.onCreate();
		Log.i("hunter", "service create");
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		this.isInterrupted = true;
		Log.i("hunter", "service destroy");
	}

	@Override
	public boolean onUnbind(Intent intent) {
		Log.i("hunter", "service unbind");
		if (player != null)
			this.stopPlayer();
		this.destroyed = true;
		return super.onUnbind(intent);
	}

	@Override
	public IBinder onBind(Intent intent) {
		Log.i("hunter", "service bind");
		context = getApplicationContext();
		return (IBinder) localBinder;
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.i("hunter", "command start");
		return super.onStartCommand(intent, flags, startId);
	}

	/**
	 * 加载音频流
	 * 
	 * @param mediaUrl
	 * @throws IOException
	 */
	public void startStreaming(final String mediaUrl) {
		Log.v("music", "startStreaming");
		r = new Runnable() {
			public void run() {
				downloadAudioIncrement(mediaUrl);
			}
		};
		playerThread = new Thread(r);
		playerThread.start();
	}

	/**
	 * 下载音频流
	 * 
	 * @param mediaUrl
	 * @throws IOException
	 */
	private void downloadAudioIncrement(String mediaUrl) {
		Log.v("music", "downloadAudioIncrement");
		URLConnection cn;
		try {
			cn = new URL(mediaUrl).openConnection();

			cn.addRequestProperty("hunter", "liantong10010xuanling");
			cn.connect();
			stream = cn.getInputStream();
			if (stream == null) {
				Log.e(getClass().getName(), "无法从此地址创建媒体流:" + mediaUrl);
			}

			downloadingMediaFile = new File(PSCTUtil.getMp3Path(), mp3.musicName + ".temp");

			if (downloadingMediaFile.exists()) {
				downloadingMediaFile.delete();
			}

			FileOutputStream out = new FileOutputStream(downloadingMediaFile);
			byte buf[] = new byte[16384];
			int totalBytesRead = 0;
			int numread;
			while (validateNotInterrupted() && (numread = stream.read(buf)) > 0) {
				out.write(buf, 0, numread);
				totalBytesRead += numread;
				totalKbRead = totalBytesRead / 1000;
				// Log.i("hunter", "***累计下载量：***" + totalKbRead);
				testMediaBuffer();
			}
			stream.close();
			if (validateNotInterrupted()) {
				fireDataFullyLoaded();
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 确认没有中断
	 * 
	 * @return
	 */
	private boolean validateNotInterrupted() {
		if (isInterrupted) {
			if (player != null) {
				player.pause();
				// mediaPlayer.release();
			}
			return false;
		} else {
			return true;
		}
	}

	/**
	 * 测试是否需要将此文件转换成媒体文件 Interacting with MediaPlayer on non-main UI thread can
	 * causes crashes to so perform this using a Handler.
	 */
	private void testMediaBuffer() {
		Runnable updater = new Runnable() {
			public void run() {
				if (player == null && !destroyed) {
					if (totalKbRead >= INTIAL_KB_BUFFER) {
						Log.i("hunter", "totalkbread>=initialkbbuffer");
						try {
							startMediaPlayer();
						} catch (Exception e) {
							Log.e(getClass().getName(), "Error copying buffered conent.", e);
						}
					}
				}
				if (!destroyed && player != null) {
					// 如果剩余时间小于1秒或者下载的大小大于50k；
					if ((player.getDuration() - player.getCurrentPosition() <= 1000)
							&& (totalKbRead - readHistory) > 50) {
						Log.i("hunter", player.getDuration() + "||" + player.getCurrentPosition());
						transferBufferToMediaPlayer(false);
					}
				}
			}
		};
		handler.post(updater);
	}

	/**
	 * 开始播放临时音乐文件
	 */
	private void startMediaPlayer() {
		try {
			File bufferedFile = new File(PSCTUtil.getMp3Path(), mp3.musicName + "_play_"
					+ (count++) + ".temp");
			Log.v("hunter", "startMediaPlayer");
			moveFile(downloadingMediaFile, bufferedFile);
			Log.v(getClass().getName(), "Buffered File path: " + bufferedFile.getAbsolutePath());
			Log.v(getClass().getName(), "Buffered File length: " + bufferedFile.length() + "");

			player = createMediaPlayer(bufferedFile);
			player.start();
		} catch (IOException e) {
			Log.e(getClass().getName(), "Error initializing the MediaPlayer.", e);
			return;
		}
	}

	public void pausePlayer() {
		try {
			player.pause();
			isPause = true;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void startPlayer() {
		player.start();
		isPause = false;
	}

	public void stopPlayer() {
		destroyed = true;
		if (player == null)
			return;
		player.stop();
		player.release();
		player = null;
	}

	/**
	 * 创建一个音频播放器
	 * 
	 * @param mediaFile
	 * @return
	 * @throws IOException
	 */
	private MediaPlayer createMediaPlayer(File mediaFile) throws IOException {
		MediaPlayer mPlayer = new MediaPlayer();
		mPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
			public boolean onError(MediaPlayer mp, int what, int extra) {
				Log.e(getClass().getName(), "Error in MediaPlayer: (" + what + ") with extra ("
						+ extra + ")");
				return false;
			}
		});

		FileInputStream fis = new FileInputStream(mediaFile);
		mPlayer.setDataSource(fis.getFD());
		mPlayer.prepare();
		Log.v("hunter", "createMediaPlayer");
		return mPlayer;
	}

	private void transferBufferToMediaPlayer(boolean isDone) {
		try {
			if (!destroyed) {
				Log.v("hunter", "transferBufferToMediaPlayer");
				File oldBufferedFile = new File(PSCTUtil.getMp3Path(), mp3.musicName + "_play_"
						+ (count++) + ".temp");
				File bufferedFile = null;
				if (isDone) {
					bufferedFile = new File(PSCTUtil.getMp3Path(), mp3.musicName + ".mp3");
				} else {
					bufferedFile = new File(PSCTUtil.getMp3Path(), mp3.musicName + "_play_" + count
							+ ".temp");
				}
				bufferedFile.deleteOnExit();
				moveFile(downloadingMediaFile, bufferedFile);
				int curPosition = player.getCurrentPosition();
				Log.v("hunter", "转换——暂停播放-->" + curPosition / 1000 + "秒");
				player.pause();
				isPause = true;
				int bufferedLength = totalKbRead - readHistory;
				readHistory = totalKbRead;
				boolean bufferedEnough = (bufferedLength > 50);
				if (bufferedEnough || completed) {
					Log.v("hunter", "bufferedEnough" + "||" + "curposition" + curPosition / 1000
							+ "秒");
					player = createMediaPlayer(bufferedFile);
					player.seekTo(curPosition);
					Log.v("hunter", "转换——恢复播放");
					player.setOnCompletionListener(new OnCompletionListener() {

						@Override
						public void onCompletion(MediaPlayer mp) {
							if (completed) {
								stopPlayer();
								playNetMusic();
							}
						}
					});
				}
				if (bufferedEnough || completed) {
					player.start();
					isPause = false;
				}
				oldBufferedFile.delete();
			}
		} catch (Exception e) {
			Log.e(getClass().getName(), "Error updating to newly loaded content.", e);
		}
	}

	/**
	 * 下载文件已转化为媒体文件，删除下载文件
	 */
	private void fireDataFullyLoaded() {
		Runnable updater = new Runnable() {
			public void run() {
				completed = true;
				transferBufferToMediaPlayer(true);
				// 下载文件已转化为媒体文件，删除下载文件
				downloadingMediaFile.delete();
				Log.i("hunter", "下载完成，保存在本地");
			}
		};
		handler.post(updater);
	}

	public void interrupt() {
		Log.i("hunter", "interrupt");
		// playButton.setEnabled(false);
		isInterrupted = true;
		validateNotInterrupted();
	}

	/**
	 * 将就文件写入新文件
	 * 
	 * @param oldLocation
	 * @param newLocation
	 * @throws IOException
	 */
	public void moveFile(File oldLocation, File newLocation) throws IOException {
		// Log.i("hunter","move file");
		if (oldLocation.exists()) {
			BufferedInputStream reader = new BufferedInputStream(new FileInputStream(oldLocation));
			BufferedOutputStream writer = new BufferedOutputStream(new FileOutputStream(
					newLocation, false));
			try {
				byte[] buff = new byte[8192];
				int numChars;
				while ((numChars = reader.read(buff, 0, buff.length)) != -1) {
					writer.write(buff, 0, numChars);
				}
			} catch (IOException ex) {
				throw new IOException("IOException when transferring " + oldLocation.getPath()
						+ " to " + newLocation.getPath());
			} finally {
				try {
					if (reader != null) {
						writer.close();
						reader.close();
					}
				} catch (IOException ex) {
					Log.e(getClass().getName(), "Error closing files when transferring "
							+ oldLocation.getPath() + " to " + newLocation.getPath());
				}
			}
		} else {
			throw new IOException("Old location does not exist when transferring "
					+ oldLocation.getPath() + " to " + newLocation.getPath());
		}
	}

	public MediaPlayer getPlayer() {
		return this.player;
	}

	public void play(int mode) {
		switch (mode) {
		case Constant.MODEL_NOMAL:
			switchToNomal();
			break;
		case Constant.MODEL_SDCARD:
			switchToSDcard();
			break;

		case Constant.MODEL_NET:
			switchToNet();
			break;
		}
	}

	/**
	 * 切换为默认播放模式
	 */
	protected void switchToNomal() {
		if (player != null) {
			this.stopPlayer();
		}
		player = MediaPlayer.create(context, R.raw.bg_music);
		player.setLooping(true);
		player.start();
	}

	/**
	 * 切换为网络音乐
	 */
	private void switchToNet() {
		if (player != null) {
			this.stopPlayer();
		}
		if (mp3List == null || mp3List.isEmpty()) {
			ThreadPool.execute(new Runnable() {

				@Override
				public void run() {
					Mp3Res res = new HttpUtil(context).getBgMusicList();
					if (res != null) {
						if (res.res == 0) {
							mp3List = res.musicList;
							handler.post(new Runnable() {

								@Override
								public void run() {
									playNetMusic();
								}
							});
						}
					} else {
						Toast.makeText(getApplicationContext(), "网络异常", Toast.LENGTH_SHORT).show();
					}
				}
			});
		} else {
			playNetMusic();
		}

	}

	/**
	 * 切换为本地音乐播放
	 */
	private void switchToSDcard() {
		ContentResolver resolver = context.getContentResolver();
		Cursor cursor = resolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
				new String[] { MediaStore.Audio.Media.DATA }, null, null, null);
		if (cursor == null)
			return;
		final int count = cursor.getCount();
		Log.v("mp3", "sdcard mp3 count:" + count);
		final Map<Integer, String> musicMap = new HashMap<Integer, String>();
		int i = 0;
		while (cursor.moveToNext()) {
			musicMap.put(i,
					cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA)));
			i++;

		}
		cursor.close();
		if (player == null) {
			player = new MediaPlayer();
		} else {
			player.reset();
		}
		try {
			player.setDataSource(musicMap.get((int) (Math.random() * count)));
			player.prepareAsync();
			player.setOnCompletionListener(new OnCompletionListener() {

				@Override
				public void onCompletion(MediaPlayer mp) {
					player.reset();
					try {
						player.setDataSource(musicMap.get((int) (Math.random() * count)));
						player.prepare();
						player.start();
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
					} catch (SecurityException e) {
						e.printStackTrace();
					} catch (IllegalStateException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}

			});
			player.setOnPreparedListener(new OnPreparedListener() {

				@Override
				public void onPrepared(MediaPlayer mp) {
					player.start();
				}
			});
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public boolean isPlay() {
		if (player == null)
			return false;
		return player.isPlaying();
	}

	/**
	 * 随机播放一首网络背景音乐
	 */
	protected void playNetMusic() {
		mp3 = mp3List.get((int) (Math.random() * mp3List.size()));
		Log.v("music", "mp3:" + mp3.toString());
		File mp3File = new File(PSCTUtil.getMp3Path() + File.separator + mp3.musicName + ".mp3");
		if (mp3File.exists()) {// 如果以前听过在本地会保存起来，直接播放本地文件
			Log.v("music", "mp3存在，本地播放");
			player = MediaPlayer.create(context, Uri.fromFile(mp3File));
			player.setOnCompletionListener(new OnCompletionListener() {

				@Override
				public void onCompletion(MediaPlayer mp) {
					playNetMusic();
				}

			});
			player.start();
		} else {// 否则播放网络音乐并保存在本地
			String url = HttpUtil.BASE_URL + "/" + "music" + "/" + mp3.music;
			Log.v("music", "mp3Url:" + url);
			count = 0;
			destroyed = false;
			startStreaming(url);
		}
	}

	/**
	 * 广播接收器，监听用户来电用来中断和启动音乐播放
	 */
	private BroadcastReceiver phonelistener = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			if (intent.getAction().equals(Intent.ACTION_ANSWER)) {
				Log.i("hunter", "answer");
				TelephonyManager tel = (TelephonyManager) context
						.getSystemService(Context.TELEPHONY_SERVICE);
				switch (tel.getCallState()) {
				case TelephonyManager.CALL_STATE_RINGING:
					pausePlayer();
					break;
				case TelephonyManager.CALL_STATE_OFFHOOK:
					startPlayer();
					break;
				}
			}

		}
	};

	public class LocalBinder extends Binder {
		public MusicService getService() {
			return MusicService.this;
		}
	}

}